package com.chisheng.caa.service.impl;

import cn.hutool.core.util.StrUtil;
import com.chisheng.caa.config.CaaProperties;
import com.chisheng.caa.exception.IllegalArgumentException;
import com.chisheng.caa.exception.ServiceException;
import com.chisheng.caa.mapper.FileMetadataMapper;
import com.chisheng.caa.pojo.entity.FileMetadata;
import com.chisheng.caa.service.FileService;
import com.chisheng.caa.util.FileUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@Slf4j
@Service
public class FileServiceImpl implements FileService {

    @Resource
    private CaaProperties properties;

    @Resource
    private FileMetadataMapper fileMapper;

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public String upload(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if (StrUtil.isEmpty(originalFilename)) {
            throw new IllegalArgumentException("上传文件的文件名不能为空");
        }

        String root = properties.getFile().getLocalRootPath();
        String name = FileUtil.genName(FileUtil.getSuffix(originalFilename));
        String savePath = FileUtil.join(root, FileUtil.genDatePath(), name);
        File saveFile = new File(savePath);
        FileUtil.mkdirs(saveFile.getParentFile());

        try {
            FileUtils.copyInputStreamToFile(file.getInputStream(), saveFile);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new ServiceException("IO 读写错误");
        }

        try {
            FileMetadata metadata = new FileMetadata();
            metadata.setFilename(name);
            FileSystemResource resource = new FileSystemResource(saveFile);
            metadata.setUrl(resource.getURL());
            metadata.setContentType(file.getContentType());
            fileMapper.insert(metadata);
            return metadata.getFileId();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException("文件信息保存失败");
        }
    }

    @Override
    public void output(HttpServletResponse response, String fileCode) {
        FileMetadata metadata = fileMapper.selectById(fileCode);
        if (metadata == null) {
            throw new IllegalArgumentException("文件码无效");
        }

        try {
            response.setContentType(metadata.getContentType());
            String filename = URLEncoder.encode(metadata.getFilename(), StandardCharsets.UTF_8);
            response.setHeader("content-disposition", "attachment;filename=" + filename);
            FileSystemResource resource = new FileSystemResource(metadata.getUrl().getFile());
            FileUtils.copyFile(resource.getFile(), response.getOutputStream());
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new ServiceException("IO 读写错误");
        }
    }

}
